package com.work.export.service.impl;

import com.work.export.constant.Constant;
import com.work.export.service.DataExportService;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.io.*;
import java.sql.*;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

// Service 实现类
@Service
public class DataExportServiceImpl implements DataExportService {


    @Override
    @Async
    public void exportData(int threadNumber, CountDownLatch countDownLatch) throws SQLException {

        try {
            //连接jdbc
            Connection connection = DriverManager.getConnection(Constant.JDBC_URL, Constant.JDBC_USER, Constant.JDBC_PASSWORD);
            //SQL
            String query = "SELECT * FROM t_user LIMIT ?, ?";

            try (PreparedStatement preparedStatement = connection.prepareStatement(query)) {
                //设置sql语句中的？的值
                preparedStatement.setInt(1, (threadNumber - 1) * Constant.PAGE_SIZE);
                preparedStatement.setInt(2, Constant.PAGE_SIZE);
                //执行查询语句
                try (ResultSet resultSet = preparedStatement.executeQuery()) {
                    XSSFWorkbook workbook = new XSSFWorkbook();
                    XSSFSheet sheet = workbook.createSheet("Sheet1");

                    // 添加表头
                    Row headerRow = sheet.createRow(0);
                    headerRow.createCell(0).setCellValue("序号");
                    headerRow.createCell(1).setCellValue("姓名");
                    headerRow.createCell(2).setCellValue("年龄");
                    //初始行
                    int rowNum = 1;
                    //查询的sql的语句有下一步，循环创建行和列，并赋值
                    while (resultSet.next()) {
                        Row row = sheet.createRow(rowNum++);
                        row.createCell(0).setCellValue(resultSet.getInt("id"));
                        row.createCell(1).setCellValue(resultSet.getString("name"));
                        row.createCell(2).setCellValue(resultSet.getInt("age"));
                    }
                    //使用输出流把文件导出
                    try (FileOutputStream fileOut = new FileOutputStream(Constant.EXPORT_PATH + "export_thread_" + threadNumber + ".xlsx")) {
                        //写出文件
                        workbook.write(fileOut);
                    } catch (FileNotFoundException e) {
                        e.printStackTrace();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
            //关闭jdbc连接
            connection.close();
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            countDownLatch.countDown();  // 每个线程完成任务后减少计数
        }

    }

    @Override
    public void compressFilesAndDownload(List<String> fileNames, String zipFileName) {
        try {
            File zipFile = new File(Constant.EXPORT_PATH + File.separator + zipFileName);
            try (FileOutputStream fos = new FileOutputStream(zipFile);
                 ZipOutputStream zos = new ZipOutputStream(fos)) {

                for (String fileName : fileNames) {
                    File fileToZip = new File(Constant.EXPORT_PATH + File.separator + fileName);
                    try (FileInputStream fis = new FileInputStream(fileToZip)) {
                        ZipEntry zipEntry = new ZipEntry(fileName);
                        zos.putNextEntry(zipEntry);

                        byte[] bytes = new byte[1024];
                        int length;
                        while ((length = fis.read(bytes)) >= 0) {
                            zos.write(bytes, 0, length);
                        }
                        fis.close();
                    }
                }
                zos.closeEntry();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}